/**
 * 队列服务
 * EndoSight-UC 医疗AI系统
 *
 * 统一的队列操作接口
 * 提供任务提交、状态查询和管理功能
 */

import queueManager from '../config/queueConfig.js';
import { QueueType, QueuePriority } from '../config/queueConfig.js';
import structuredLogger from '../utils/structuredLogger.js';
import auditService from '../services/auditService.js';
import winston from 'winston';

// 配置日志记录器
const logger = winston.createLogger({
  level: 'info',
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.json()
  ),
  transports: [
    new winston.transports.Console({
      format: winston.format.simple()
    })
  ]
});

/**
 * 队列服务主类
 */
class QueueService {
  constructor() {
    this.isInitialized = false;
    this.jobCallbacks = new Map(); // 任务完成回调
    this.activeJobs = new Map();   // 活跃任务跟踪
  }

  /**
   * 初始化队列服务
   */
  async initialize() {
    try {
      if (this.isInitialized) {
        return true;
      }

      await queueManager.initialize();
      this.isInitialized = true;

      // 检查队列管理器状态
      if (!queueManager.redisAvailable) {
        logger.warn('⚠️ 队列服务以降级模式运行 (Redis不可用)');
      } else {
        logger.info('✅ 队列服务初始化完成');
      }
      return true;

    } catch (error) {
      logger.error('队列服务初始化失败:', error);
      // 不抛出错误，允许服务器继续运行
      this.isInitialized = true;
      logger.warn('⚠️ 队列服务将禁用，但服务器继续运行');
      return true;
    }
  }

  /**
   * 提交AI推理任务
   */
  async submitAIInferenceJob(jobData, options = {}) {
    try {
      const jobId = this.generateJobId('ai-inference');

      const enhancedJobData = {
        ...jobData,
        jobId,
        type: 'medical-image-analysis',
        timestamp: new Date().toISOString(),
        submittedAt: new Date().toISOString()
      };

      // 设置医疗优先级
      let priority = QueuePriority.NORMAL;
      if (jobData.isEmergency) {
        priority = QueuePriority.CRITICAL;
        enhancedJobData.jobType = 'urgent-analysis';
      } else if (jobData.isBatch) {
        enhancedJobData.jobType = 'batch-analysis';
      }

      const jobOptions = {
        ...options,
        priority,
        attempts: 5, // AI推理重试更多次
        backoff: {
          type: 'exponential',
          delay: 3000
        },
        // HIPAA合规设置
        settings: {
          encrypt: process.env.NODE_ENV === 'production'
        }
      };

      const job = await queueManager.addJob(
        QueueType.AI_INFERENCE,
        enhancedJobData,
        jobOptions
      );

      // 记录任务提交审计日志
      await auditService.logAIInference(
        jobData.userId,
        jobData.sessionId,
        jobData.patientId,
        jobData.taskId,
        'job-submitted',
        jobData.imagePath || jobData.imageData,
        null,
        'pending',
        null,
        new Date().toISOString(),
        0,
        jobData.imageSize || 0,
        0,
        {
          jobId: job.id,
          queueType: QueueType.AI_INFERENCE,
          priority,
          submittedBy: jobData.userId
        }
      );

      // 跟踪活跃任务
      this.activeJobs.set(jobId, {
        id: jobId,
        queueId: job.id,
        type: 'ai-inference',
        status: 'pending',
        submittedAt: new Date().toISOString(),
        userId: jobData.userId
      });

      logger.info('AI推理任务已提交', {
        jobId: job.id,
        taskId: jobData.taskId,
        priority,
        userId: jobData.userId
      });

      return {
        success: true,
        jobId: job.id,
        taskId: jobData.taskId,
        status: 'pending',
        estimatedDuration: this.getEstimatedDuration('ai-inference'),
        timestamp: new Date().toISOString()
      };

    } catch (error) {
      logger.error('提交AI推理任务失败:', error);
      throw error;
    }
  }

  /**
   * 提交文件处理任务
   */
  async submitFileProcessingJob(jobData, options = {}) {
    try {
      const jobId = this.generateJobId('file-processing');

      const enhancedJobData = {
        ...jobData,
        jobId,
        type: 'medical-image-upload',
        timestamp: new Date().toISOString(),
        submittedAt: new Date().toISOString()
      };

      // 确定处理类型
      let jobType = 'medical-image-upload';
      if (jobData.fileSize > 10 * 1024 * 1024) { // 大于10MB
        jobType = 'large-file-streaming';
        enhancedJobData.chunkCount = Math.ceil(jobData.fileSize / (5 * 1024 * 1024)); // 5MB分块
      }

      enhancedJobData.jobType = jobType;

      const jobOptions = {
        ...options,
        priority: options.priority || QueuePriority.NORMAL,
        attempts: 3,
        delay: options.delay || 0
      };

      const job = await queueManager.addJob(
        QueueType.FILE_PROCESSING,
        enhancedJobData,
        jobOptions
      );

      // 记录文件操作审计日志
      await auditService.logFileOperation(
        jobData.userId,
        jobData.sessionId,
        'upload',
        jobData.fileName,
        jobData.filePath,
        jobData.fileType,
        jobData.fileSize,
        null, // fileHash将在处理时生成
        jobData.mimeType,
        true, // medical_image
        jobData.patientId,
        jobData.taskId,
        null, // upload_result待处理完成时更新
        null, // validation_result待处理完成时更新
        null, // storage_location
        true, // access_granted
        null, // access_denied_reason
        true, // retention_required
        null, // retention_until
        false, // gdpr_data
        {
          jobId: job.id,
          queueType: QueueType.FILE_PROCESSING,
          jobType,
          submittedBy: jobData.userId
        }
      );

      // 跟踪活跃任务
      this.activeJobs.set(jobId, {
        id: jobId,
        queueId: job.id,
        type: 'file-processing',
        status: 'pending',
        submittedAt: new Date().toISOString(),
        userId: jobData.userId
      });

      logger.info('文件处理任务已提交', {
        jobId: job.id,
        fileName: jobData.fileName,
        fileSize: jobData.fileSize,
        userId: jobData.userId
      });

      return {
        success: true,
        jobId: job.id,
        fileName: jobData.fileName,
        status: 'pending',
        estimatedDuration: this.getEstimatedDuration('file-processing'),
        timestamp: new Date().toISOString()
      };

    } catch (error) {
      logger.error('提交文件处理任务失败:', error);
      throw error;
    }
  }

  /**
   * 提交清理任务
   */
  async submitCleanupJob(jobData, options = {}) {
    try {
      const jobId = this.generateJobId('cleanup');

      const enhancedJobData = {
        ...jobData,
        jobId,
        timestamp: new Date().toISOString()
      };

      const jobOptions = {
        ...options,
        priority: options.priority || QueuePriority.LOW,
        attempts: 1,
        delay: options.delay || 0
      };

      const job = await queueManager.addJob(
        QueueType.CLEANUP,
        enhancedJobData,
        jobOptions
      );

      logger.info('清理任务已提交', {
        jobId: job.id,
        cleanupType: jobData.cleanupType
      });

      return {
        success: true,
        jobId: job.id,
        cleanupType: jobData.cleanupType,
        status: 'pending',
        timestamp: new Date().toISOString()
      };

    } catch (error) {
      logger.error('提交清理任务失败:', error);
      throw error;
    }
  }

  /**
   * 获取任务状态
   */
  async getJobStatus(jobId) {
    try {
      const jobInfo = this.activeJobs.get(jobId);
      if (!jobInfo) {
        return {
          success: false,
          message: '任务不存在或已完成',
          jobId
        };
      }

      // 从队列获取任务状态
      const queue = queueManager.getQueue(jobInfo.queueType);
      if (!queue) {
        return {
          success: false,
          message: '队列不可用',
          jobId
        };
      }

      const job = await queue.getJob(jobInfo.queueId);
      if (!job) {
        // 任务可能已完成，从活跃任务中移除
        this.activeJobs.delete(jobId);
        return {
          success: true,
          jobId,
          status: 'completed',
          message: '任务已完成'
        };
      }

      const jobState = await job.getState();
      const progress = job.progress();

      // 更新活跃任务状态
      jobInfo.status = jobState;
      jobInfo.progress = progress;
      jobInfo.updatedAt = new Date().toISOString();
      this.activeJobs.set(jobId, jobInfo);

      return {
        success: true,
        jobId,
        status: jobState,
        progress,
        data: job.data,
        createdAt: new Date(job.timestamp).toISOString(),
        updatedAt: jobInfo.updatedAt,
        attemptsMade: job.attemptsMade,
        processedOn: job.processedOn,
        finishedOn: job.finishedOn
      };

    } catch (error) {
      logger.error('获取任务状态失败:', error);
      return {
        success: false,
        message: '获取任务状态失败',
        error: error.message,
        jobId
      };
    }
  }

  /**
   * 获取队列状态
   */
  async getQueueStatus() {
    try {
      const status = await queueManager.getQueueStatus();

      // 添加活跃任务信息
      const activeJobsByType = {};
      for (const [jobId, jobInfo] of this.activeJobs) {
        if (!activeJobsByType[jobInfo.type]) {
          activeJobsByType[jobInfo.type] = 0;
        }
        activeJobsByType[jobInfo.type]++;
      }

      return {
        ...status,
        activeJobs: this.activeJobs.size,
        activeJobsByType,
        isInitialized: this.isInitialized
      };

    } catch (error) {
      logger.error('获取队列状态失败:', error);
      throw error;
    }
  }

  /**
   * 取消任务
   */
  async cancelJob(jobId, userId) {
    try {
      const jobInfo = this.activeJobs.get(jobId);
      if (!jobInfo) {
        return {
          success: false,
          message: '任务不存在',
          jobId
        };
      }

      // 检查权限
      if (jobInfo.userId !== userId) {
        return {
          success: false,
          message: '无权限取消此任务',
          jobId
        };
      }

      const queue = queueManager.getQueue(jobInfo.queueType);
      if (!queue) {
        return {
          success: false,
          message: '队列不可用',
          jobId
        };
      }

      const job = await queue.getJob(jobInfo.queueId);
      if (!job) {
        this.activeJobs.delete(jobId);
        return {
          success: false,
          message: '任务已完成或不存在',
          jobId
        };
      }

      await job.remove();
      this.activeJobs.delete(jobId);

      // 记录取消审计日志
      await structuredLogger.audit('JOB_CANCELLED', 'queue', userId, {
        jobId,
        jobType: jobInfo.type,
        cancelledBy: userId,
        cancelledAt: new Date().toISOString()
      });

      logger.info('任务已取消', {
        jobId,
        jobType: jobInfo.type,
        cancelledBy: userId
      });

      return {
        success: true,
        jobId,
        message: '任务已取消',
        timestamp: new Date().toISOString()
      };

    } catch (error) {
      logger.error('取消任务失败:', error);
      return {
        success: false,
        message: '取消任务失败',
        error: error.message,
        jobId
      };
    }
  }

  /**
   * 批量获取任务状态
   */
  async getBatchJobStatus(jobIds) {
    try {
      const results = [];

      for (const jobId of jobIds) {
        const status = await this.getJobStatus(jobId);
        results.push(status);
      }

      return {
        success: true,
        results,
        total: jobIds.length,
        timestamp: new Date().toISOString()
      };

    } catch (error) {
      logger.error('批量获取任务状态失败:', error);
      return {
        success: false,
        message: '批量获取任务状态失败',
        error: error.message
      };
    }
  }

  /**
   * 清理完成的任务
   */
  async cleanupCompletedJobs(maxAge = 3600000) { // 默认1小时
    try {
      const now = Date.now();
      const completedJobs = [];

      for (const [jobId, jobInfo] of this.activeJobs) {
        const jobAge = now - new Date(jobInfo.submittedAt).getTime();

        if (jobAge > maxAge ||
            jobInfo.status === 'completed' ||
            jobInfo.status === 'failed') {
          completedJobs.push(jobId);
        }
      }

      // 从活跃任务中移除
      for (const jobId of completedJobs) {
        this.activeJobs.delete(jobId);
      }

      logger.info('已清理完成的任务', {
        cleanedCount: completedJobs.length,
        remainingActiveJobs: this.activeJobs.size
      });

      return {
        success: true,
        cleanedCount: completedJobs.length,
        remainingActiveJobs: this.activeJobs.size,
        timestamp: new Date().toISOString()
      };

    } catch (error) {
      logger.error('清理完成任务失败:', error);
      return {
        success: false,
        message: '清理完成任务失败',
        error: error.message
      };
    }
  }

  /**
   * 注册任务完成回调
   */
  registerJobCallback(jobId, callback) {
    this.jobCallbacks.set(jobId, callback);
  }

  /**
   * 触发任务完成回调
   */
  triggerJobCallback(jobId, result) {
    const callback = this.jobCallbacks.get(jobId);
    if (callback) {
      try {
        callback(result);
      } catch (error) {
        logger.error('任务回调执行失败:', error);
      }
      this.jobCallbacks.delete(jobId);
    }
  }

  /**
   * 生成任务ID
   */
  generateJobId(type) {
    const timestamp = Date.now();
    const random = Math.random().toString(36).substr(2, 9);
    return `${type}_${timestamp}_${random}`;
  }

  /**
   * 获取预估处理时间
   */
  getEstimatedDuration(jobType) {
    const durations = {
      'ai-inference': 3000,      // 3秒
      'file-processing': 5000,   // 5秒
      'cleanup': 10000,         // 10秒
      'validation': 2000        // 2秒
    };

    return durations[jobType] || 5000;
  }

  /**
   * 获取队列统计信息
   */
  async getQueueStatistics() {
    try {
      const queueStatus = await this.getQueueStatus();

      const statistics = {
        queueStatus,
        performance: {
          totalActiveJobs: this.activeJobs.size,
          jobsByType: {},
          averageWaitTime: 0,
          successRate: 0
        },
        timestamp: new Date().toISOString()
      };

      // 计算各类型任务统计
      for (const [jobId, jobInfo] of this.activeJobs) {
        const type = jobInfo.type;
        if (!statistics.performance.jobsByType[type]) {
          statistics.performance.jobsByType[type] = {
            active: 0,
            pending: 0,
            processing: 0,
            completed: 0,
            failed: 0
          };
        }
        statistics.performance.jobsByType[type].active++;
      }

      return statistics;

    } catch (error) {
      logger.error('获取队列统计信息失败:', error);
      throw error;
    }
  }

  /**
   * 健康检查
   */
  async healthCheck() {
    try {
      if (!this.isInitialized) {
        return {
          status: 'unhealthy',
          message: '队列服务未初始化'
        };
      }

      const queueStatus = await this.getQueueStatus();

      // 检查Redis连接
      if (!queueStatus.redis || queueStatus.redis.totalConnections === 0) {
        return {
          status: 'unhealthy',
          message: 'Redis连接异常'
        };
      }

      // 检查队列状态
      const unhealthyQueues = Object.entries(queueStatus.queues)
        .filter(([name, status]) => status.active > 10) // 超过10个活跃任务认为不健康
        .map(([name]) => name);

      if (unhealthyQueues.length > 0) {
        return {
          status: 'degraded',
          message: `部分队列负载过高: ${unhealthyQueues.join(', ')}`,
          unhealthyQueues
        };
      }

      return {
        status: 'healthy',
        message: '队列系统运行正常',
        queueCount: Object.keys(queueStatus.queues).length,
        totalJobs: Object.values(queueStatus.queues).reduce((sum, queue) => sum + queue.total, 0)
      };

    } catch (error) {
      logger.error('队列健康检查失败:', error);
      return {
        status: 'unhealthy',
        message: '健康检查失败',
        error: error.message
      };
    }
  }
}

// 创建并导出队列服务实例
const queueService = new QueueService();

export default queueService;